package com.zero.zeroframe.utils

import android.app.Activity
import android.content.Intent
import android.content.pm.ActivityInfo
import android.graphics.Color
import android.net.Uri
import androidx.lifecycle.LifecycleCoroutineScope
import com.blankj.utilcode.util.UriUtils
import com.lxj.androidktx.AndroidKTX
import com.lxj.androidktx.core.toast
import com.lxj.androidktx.luban.Luban
import com.lxj.androidktx.picker.KTXCameraActivity
import com.lxj.androidktx.picker.PickerEmptyActivity
import com.lxj.androidktx.picker._PickerData
import com.lxj.androidktx.util.DirManager
import com.lxj.androidktx.util.UriHelper
import com.yalantis.ucrop.UCrop
import com.zero.zeroframe.popup.LoadingPopup
import com.zhihu.matisse.Matisse
import com.zhihu.matisse.MimeType
import com.zhihu.matisse.engine.impl.GlideEngine
import com.zhihu.matisse.internal.entity.CaptureStrategy
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File

/**
 * 图片和视频选择器，整合了Matisse，uCrop和Luban。
 * 获取结果有两种方式（二选一），onFinish回调和onActivityResult
 */
object ImagePickerUtil {
    private const val _pickerCode = 1000
    private const val _cameraCode = 1001
    private const val _cropCode = 1002
    private lateinit var pickerData:_PickerData
    private var activity: Activity?= null
    private var onFinish: ((List<String>)->Unit)?= null

    /**
     * @param reqCode 如果你想通过onActivityResult方法获取结果时就传递
     * @param isCrop 是否开启裁剪，默认false
     * @param isCompress 是否使用Luban压缩，默认是true
     */
    fun startCamera(from: Activity, reqCode: Int = 1000, isCrop: Boolean = false, isCompress: Boolean = true,
                    onFinish: ((List<String>)->Unit)) {
        activity = from
        this.onFinish = onFinish
        pickerData = _PickerData(
            isCrop = isCrop, action = "camera", maxNum = 1, isCompress = isCompress
        )
        val intent = Intent(from, KTXCameraActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
        from.startActivityForResult(intent, 1001)
    }

    /**
     * 直接开启选择器，选择器自带拍摄功能，注意：maxNum>1时和types包含video时无法使用裁剪；types包含video时无法使用压缩
     * @param reqCode 如果你想通过onActivityResult方法获取结果时就传递
     * @param isCrop 是否开启裁剪，默认false
     * @param isCompress 是否使用Luban压缩，默认是true
     * @param maxNum 最多选择数量，默认是1
     * @param types 选择的类型，默认是Image类型
     * @param maxVideoSize 最大视频大小，默认是20M
     * @param showCapture 是否显示拍照
     * @param spanCount
     */
    fun startPicker(from: Activity, reqCode: Int = 1000, isCrop: Boolean = false, isCompress: Boolean = true,
                    maxNum: Int = 1, types: Set<MimeType> = MimeType.ofImage(),
                    maxVideoSize: Long = 0, showCapture: Boolean = true, spanCount: Int = 4,
                    onFinish: ((List<String>)->Unit)) {
        activity = from
        this.onFinish = onFinish
        val max = if(maxNum < 1) 1 else maxNum
        //必须三个条件同时成立，才能开启裁剪
        val canCrop = isCrop && max==1 && !types.containsAll(MimeType.ofVideo())
        pickerData = _PickerData(
            isCrop = canCrop, maxNum = max, types = types, action = "picker", isCompress = isCompress,
            maxVideoSize = maxVideoSize, showCapture = showCapture, spanCount = spanCount
        )
        Matisse.from(from).choose(pickerData.types).countable(true)
            .capture(pickerData.showCapture)
            .spanCount(pickerData.spanCount)
            .captureStrategy(
                CaptureStrategy(
                    true,
                    "${AndroidKTX.context.packageName}.fileprovider",
                    "picker"
                )
            )
            .theme(com.lxj.androidktx.R.style.Matisse_Dracula)
            .maxSelectable(pickerData.maxNum)
            .showSingleMediaType(true)
            .addFilter(PickerEmptyActivity.VideoSizeFilter(maxSize = if (pickerData.maxVideoSize > 0) pickerData.maxVideoSize else 20 * 1024 * 1024))
            //.gridExpectedSize(resources.getDimensionPixelSize(R.dimen.grid_expected_size))
            .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
            //.thumbnailScale(0.6f)
            .imageEngine(GlideEngine())
            .showPreview(true) // Default is `true`
            .forResult(reqCode)
    }

    /**
     * 获取结果，返回的是文件路径列表。适用于通过onActivityResult获取数据
     */
    fun fetchResult(data: Intent?): ArrayList<String>{
        val list = fetchUriResult(data)
        val paths = arrayListOf<String>()
        list.forEach {
            UriHelper.grantPermissions(data, it, true)
            paths.add(UriUtils.uri2File(it).absolutePath)
        }
        return paths
    }

    /**
     * uri列表转路径列表
     */
    fun uriListToPathList(uriList: List<Uri>): List<String>{
        val paths = arrayListOf<String>()
        uriList.forEach {
            paths.add(UriUtils.uri2File(it).absolutePath)
        }
        return paths
    }

    /**
     * 获取结果，返回的是uri列表。适用于通过onActivityResult获取数据
     */
    fun fetchUriResult(data: Intent?): ArrayList<Uri>{
        val list = data?.getParcelableArrayListExtra<Uri>("result") ?: arrayListOf()
        list.forEach {
            UriHelper.grantPermissions(data, it, true)
        }
        return list
    }

    fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?, lifecycleCoroutineScope: LifecycleCoroutineScope){
        if (resultCode == Activity.RESULT_OK ) {
            val list = arrayListOf<Uri>()
            if (requestCode == _pickerCode && data != null) {
                //打开照片和视频选择器
                list.clear()
                list.addAll(Matisse.obtainResult(data))
                if (list.isEmpty()) {
                    finishWithResult(arrayListOf())
                    return
                }
                if (pickerData.isCrop) {
                    //裁剪
                    startCrop(uri = list[0])
                } else {
                    //看看是否需要压缩
                    tryCompressImgs(list, lifecycleCoroutineScope)
                }
            } else if (requestCode == _cameraCode && data?.data != null) {
                list.clear()
                list.add(data.data!!)
                //拍照
                if (pickerData.isCrop) {
                    //裁剪
                    startCrop(uri = list[0])
                } else {
                    //看看是否需要压缩
                    tryCompressImgs(list, lifecycleCoroutineScope)
                }
            } else if (requestCode == _cropCode && data != null) {
                val cropUri = UCrop.getOutput(data)
                if (cropUri == null) {
                    toast("crop failed")
                    finishWithResult(arrayListOf())
                    return
                }
                list.clear()
                list.add(cropUri)
                tryCompressImgs(list, lifecycleCoroutineScope)
            } else {
                finishWithResult(arrayListOf())
            }
        }
    }

    fun finishWithResult(list: ArrayList<Uri>) {
        activity?:return
        onFinish?.invoke(uriListToPathList(list))
//        ImagePicker.onFinish?.invoke(list)
//        val intent = Intent()
//        intent.putParcelableArrayListExtra("result", list)
//        activity!!.setResult(Activity.RESULT_OK, intent)
//        activity!!.finish()
    }

    private fun tryCompressImgs(list: ArrayList<Uri>, lifecycleCoroutineScope: LifecycleCoroutineScope) {
        //如果未开启压缩，或者是视频，都直接返回原文件
        if (!pickerData!!.isCompress || pickerData!!.types.containsAll(MimeType.ofVideo())) {
            finishWithResult(list)
            return
        }

        LoadingPopup.show()
        lifecycleCoroutineScope.launch(Dispatchers.IO) {
            val compressUris = arrayListOf<Uri>()
            try {
                list.forEach {
                    val f = compressImage(it).await()
//                    FileUtils.delete(UriUtils.uri2File(it))
                    compressUris.add(f)
                }
                withContext(Dispatchers.Main) {
                    LoadingPopup.hide()
                    finishWithResult(compressUris)
                }
            } catch (e: Exception) {
                //如果发生异常，则返回原图
                e.printStackTrace()
                withContext(Dispatchers.Main) {
                    LoadingPopup.hide()
                    finishWithResult(compressUris)
                }
            }
        }
    }

    private fun compressImage(uri: Uri): Deferred<Uri> {
        val deferred = CompletableDeferred<Uri>()
        deferred.complete(
            UriUtils.file2Uri(
                Luban.with(AndroidKTX.context)
                    .load(UriUtils.uri2File(uri))
                    .ignoreBy(100)
                    .get()[0]
            )
        )
        return deferred
    }

    private var cropImageFile: File? = null
    private fun startCrop(uri: Uri) {
        activity?:return
        val options = UCrop.Options()
        options.setCompressionQuality(90)
        val primaryColor = Color.parseColor("#263237") //Matisse的主题色
        options.setToolbarColor(primaryColor)
        options.setToolbarWidgetColor(Color.WHITE)
        options.setStatusBarColor(Color.parseColor("#1D282C"))//Matisse的主题色
        options.setActiveControlsWidgetColor(primaryColor)
        options.setHideBottomControls(true)
        cropImageFile = File(DirManager.tempDir, "_ktx_${System.currentTimeMillis()}_crop.jpg")
        UCrop.of(uri, Uri.fromFile(cropImageFile))
            .withAspectRatio(1f, 1f)
            .withOptions(options)
            .start(activity!!, _cropCode)
    }
}